; ** por compatibilidad se omiten tildes **
; ==============================================================================
; TRABAJO PRACTICO 3 - System Programming - ORGANIZACION DE COMPUTADOR II - FCEN
; ==============================================================================
; KERNEL

BITS 16

%include "macrosmodoreal.mac"
%include "macrosmodoprotegido.mac"

%define KORG 0x1200

global start
extern pintar

extern tarea_inicial
extern tarea_idle
extern tsss

extern cargarInicial
extern cargarIdle
extern cargar_tareas

extern inicializar_scheduler
extern inicializar_arena

extern gdt
extern GDT_DESC
extern IDT_DESC
extern inicializar_idt

extern inicializar_mmu
extern inicializar_dir_tarea

extern deshabilitar_pic
extern resetear_pic
extern habilitar_pic

; PUNTO DE ENTRADA DEL KERNEL
start:
		cli ;pues que no me interrumpan por ahora
		jmp bienvenida

		;aca ponemos todos los mensajes
		iniciando: db 'Iniciando el kernel'
		iniciando_len equ $ - iniciando

bienvenida:
		IMPRIMIR_MODO_REAL iniciando, iniciando_len, 0x07, 0, 0

		; habilitar A20
		call deshabilitar_A20
		call checkear_A20
		call habilitar_A20
		call checkear_A20
		
		; dehsabilitar las interrupciones
		cli		
		
		; cargar la GDT
		lgdt [GDT_DESC]
		
		; setear el bit PE del registro CR0
		mov eax, cr0
		or eax, 1
		mov cr0, eax ;Activamos el bit P de protegido
		
		; pasar a modo protegido
		;Queremos que CS vaya a 0x50 (Indice A de GDT) (Codigo Nivel 0)
		jmp 0x50:mp ;Selector de segmento es el {index: A | gdt: 0 | rpl: 00}
						 
BITS 32 

TSSIDLE_offset: dd 0	;Offset del selector de la TSS de tarea inicial
TSSIDLE_selector: dw 0	;Selector de la TSS de tarea idle

		mp:				
		; acomodar los segmentos (ds, es, gs, ss, fs)
		xor eax, eax
		mov ax, 1100000b	;{index: C | gdt: 0 | rpl: 00}
		mov ds, ax			;ds selector de segmento de datos de la ubicación 12
		mov es, ax
		mov gs, ax
		mov ss, ax
		
		mov ax, 1110000b	;{index: E | gdt: 0 | rpl: 00}
		mov fs, ax			;fs selector de segmento de video de la ubicación 14
		
		; seteo la pila del kernel a la dirección propuesta en el ejercicio         
		mov ebp, 0x21000
		mov esp, ebp
		
		; pintar pantalla, todos los colores, que bonito!
		mov ecx, 80*25*2 	;Cantidad de Bytes de la pantalla
		sub ecx, 2			;Sacamos el primer elemento
		mov ax, 0xf000		;{blink: 0b| fondo: 111b| brillante: 0b| caracter: 000b| caracterASCII: 0x00}
	
			;Limpia la pantalla:
		limpiarPantalla:
			mov [fs:ecx], ax 	;pintamos de gris toda la pantalla
			dec ecx		
			loop limpiarPantalla
		mov [fs:ecx], ax		;faltaba pi nta el primer elemento	
		
			;Primera fila negra
		mov ecx, 80*2			;80 columnas de 2Bytes cada una
		sub ecx, 2
		mov ax, 0x0F00			;{blink: 0b| fondo: 000b| brillante: 1b| caracter: 111b| caracterASCII: 0x00}
		primeraFila:
			mov[fs:ecx], ax
			dec ecx
			loop primeraFila
		mov [fs:ecx], ax
		
			;Ultima fila negra
		mov ecx, 80*2			;80 columnas de 2Bytes cada una
		mov ebx, 25*80*2
		sub ecx, 2
		sub ebx, 2
		mov ax, 0x0F00			;{blink: 0b| fondo: 000b| brillante: 1b| caracter: 111b| caracterASCII: 0x00}
		ultimaFila:
			mov [fs:ebx], ax
			dec ecx
			sub ebx, 2
			loop ultimaFila
		mov [fs:ebx], ax
		
		
	; EJ 2
		; inicializar la IDT
		call inicializar_idt
		lidt [IDT_DESC]
		
		;--EJEMPLO DIVISION POR CERO - DIVIDE ERROR para que salte interrupcion:--
		;mov ebx, 0
		;div ebx
		
	;EJ 3				
		; inicializar el directorio de paginas y la tabla de paginas haciendo Identity Mapping de 0x000000 a 0x1fffff
		call page_init
		
		; habilitar paginacion
		mov eax, 0x21000		;cargo la direccion del directorio en cr3
		mov cr3, eax

		mov eax, cr0				
		or  eax, 0x80000000		;habilito paginacion
		mov cr0, eax
		
		; imprimimos el nombre del grupo en la parte de arriba en Blanco
		jmp imprimirGrupo
			grupoTP: db 'Los Paraguas'
			longGrupoTP: equ $ - grupoTP	
		imprimirGrupo:
			IMPRIMIR_TEXTO grupoTP, longGrupoTP, 0x0F, 0, 0 
		
	;EJ 4	
		call inicializar_mmu
		
		mov ebx, cr3 	;Guardamos cr3
		
		;Inicializamos las tarea
		;xchg bx, bx					
			
			mov eax, 1
			push eax	
			call inicializar_dir_tarea
			add esp, 4
						
		mov cr3, eax	;Cambiamos el cr3 al recien creado (sería la tarea 1)
						
		; Imprimimos algo con el mapa de memoria cambiado (cambiamos de color (VERDE) la primera columna de la fila 1)
		jmp imprimirAlgo
			probarEj4: db ' '		
		
		imprimirAlgo:
			IMPRIMIR_TEXTO probarEj4, 1, 0xA0, 1, 0 
		
		;xchg bx, bx			
			IMPRIMIR_TEXTO probarEj4, 1, 0x70, 1, 0 
				
		mov cr3, ebx ;Retorno al mapa de memoria original
		
		
		;Ej 5: Remapeamos la PIC para que las interrupciones que genere no se choquen con las de la CPU
		call deshabilitar_pic
		call resetear_pic
		call habilitar_pic
		
		sti	;Habilitamos las interrupciones para poder imprimir números del teclado, el reloj y la interrupcion 0x45
		
		;Cargamos la tarea_inicial en la GDT
			mov eax, tarea_inicial
			push eax
			call cargarInicial ;Solo cargamos la tarea inicial a la GDT
			add esp, 4
			
			; Cargamos el TR con el selector de la TSS de tarea inicial
			mov ebx, 1	;Indice en la GDT			
			shl ebx, 3	;Como ebx tiene el indice_gdt de la tarea_inicial, corremos 12 bits hacia la izquierda para obtener el offset
			mov ax, bx
			ltr ax		;Ponemos en TR el selector de segmento de la tarea incial que es la que se esta ejecutando en este momento
		
		;Cargamos la tarea_idle en la GDT
			mov eax, tarea_idle
			push eax
			mov eax, cr3
			push eax
			call cargarIdle 
			add esp,8
					
					
		;Cargamos las 5 tareas
			mov eax, tsss
			push eax
			call cargar_tareas
			add esp, 4
		
		;Inicializamos el scheduler
		call inicializar_scheduler
		call inicializar_arena		;cargamos la arena para que se vean las posiciones desde el principio sin tener que
									;esperar al primer reloj
		
		;Saltamos a la tarea idle
		mov eax, 2	;Indice de la tarea Idle = 2
		shl eax, 3	;Como eax tiene el indice_gdt de la tarea_idle, corremos 12 bits hacia la izquierda para obtener el offset
		
		mov [TSSIDLE_selector], ax
		jmp far [TSSIDLE_offset]
		
		jmp $

%include "a20.asm"
%include "paging.asm"
